<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    // 科里化 ：curry     把多元参数转换成一元参数的过程；
    // js里面典型的柯里化函数 bind()

    /* function curry (fn, args) {
      // 获取函数需要的参数长度
      let length = fn.length
      args = args || []
      // return 出去一个函数
      return function () {
        let subArgs = args.slice(0)
        // 拼接得到现有的所有函数
        subArgs.forEach((item, ind) => {
          item.push(arguments[ind])
        })
        // 判断条件 参数长度是否已经满足函数需要参数的长度
        if (subArgs.length >= length) {
          return fn.apply(this, subArgs)
        } else {
          // 如果不满足 则进入递归柯里化函数 等待参数传入
          return curry.call(this, fn, subArgs)
        }
      }
    }
    // 应用1  参数确定: 累加参数确定
    function sum (a, b, c, d) {
      return a + b + c + d
    }
    let curried = curry(sum)
    console.log(curried(1)); */

    // 应用2  参数不确定 参数还需无限累加
    // function add(arr){
    //   return arr.redcuce((acc,item)=>{
    //     return acc + item
    //   },0)
    // }



    function add (a, b, c, d) {
      return a + b + c + d;
    }
    // add();
    // 函数的长度就是参数的个数
    console.log(add.length);// 4个参数 所以函数长度是4
    // 处理多参数的curry ，不定参数的curry
    function curry (add) {
      return function curryFn (...args) {
        console.log(...args);
        if (add.length > args.length) {
          // 如果参数不够 就进入递归 继续执行函数 ，连接传入的参数 ；
          return function (...args2) {
            console.log('a'); // 执行三次
            return curryFn(...args, ...args2);
          }
        } else {
          console.log('b'); // 执行了一次
          // 如果参数已经够了 ，直接执行函数返还函数结果
          return add(...args);
        }
      }
    }

    let myadd = curry(add);
    console.log(myadd);
    // myadd
    /* 
    执行过程:
    1.执行myadd函数 传入参数1  然后执行curry 传入参数1   进入curry函数 
    2.curry函数里有一个递归 如果 add函数的长度>curry函数的长度 那么 合并curry的参数  
    3.如果add函数的长度=<curry函数的长度 那么输出当前合并后的参数
    */

    let res = myadd(1)(2)(3)(4);
    console.log(res);

  </script>
</body>

</html>